#include "data_flood.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>

char num_buff[NUMBER_BUFF_LEN] = {0};
char random_str_buff[RANDOM_STR_BUFF_LEN] = {0};

static const int8 hexlookup[128] = {
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

void df_error(const char *fmt,...)
{
	va_list		args;

	fputs("[ERROR] ", stdout);
	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
	fputc('\n', stdout);
	exit(1);
}

void df_log(const char *fmt,...)
{
	va_list		args;

	fputs("[LOG] ", stdout);
	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
	fputc('\n', stdout);
}

void df_info(const char *fmt,...)
{
	va_list		args;

	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
	fputc('\n', stdout);
}

void df_log_0(const char *fmt,...)
{
	va_list		args;
	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
	fputc('\n', stdout);
}

void df_debug(const char *fmt,...)
{
	va_list		args;

	if(!user_arg.verbose)
		return;

	fputs("[DEBUG] ", stdout);
	va_start(args, fmt);
	vfprintf(stdout, fmt, args);
	va_end(args);
	fputc('\n', stdout);
}

void df_exit(char* exit_words)
{
	if(exit_words)
		df_log("%s", exit_words);
	exit(1);
}

char* df_malloc(uint64 size)
{
	char* result = NULL;

	result = malloc(size);
	memset(result, 0, size);
	return result;
}

uint32 str_to_uint32(char* str)
{
	uint32 result = 0;

	if(1 != sscanf(str, "%u", &result)) {
		df_error("str_to_uint32 %s", str);
	}

	return result;
}

int str_to_int32(char* str)
{
	int result = 0;

	if(1 != sscanf(str, "%d", &result)) {
		df_error("str_to_int32 %s", str);
	}

	return result;
}

char* int_to_string(int value, char* buff)
{
	sprintf(buff, "%d", value);
	return buff;
}

char* int64_to_string(int64 value, char* buff)
{
	sprintf(buff, "%ld", value);
	return buff;
}

char get_hex(const char *cp)
{
	unsigned char c = (unsigned char) *cp;
	int			res = -1;

	if (c < 127)
		res = hexlookup[c];

	if (res < 0)
		df_error("invalid hexadecimal digit");

	return (char) res;
}

uint64 hex_decode(const char *src, size_t len, char *dst)
{
	const char *s,
			   *srcend;
	char		v1,
				v2,
			   *p;

	srcend = src + len;
	s = src;
	p = dst;
	while (s < srcend)
	{
		if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\r')
		{
			s++;
			continue;
		}
		v1 = get_hex(s) << 4;
		s++;
		if (s >= srcend)
			df_error("invalid hexadecimal data: odd number of digits");

		v2 = get_hex(s);
		s++;
		*p++ = v1 | v2;
	}

	return p - dst;
}

uint64 str_exchange(const char *src, size_t len, char *dst)
{
	const char *end = src + len;
	uint8 sum = 0;

	while (src < end)
	{
		sum += *src;
		*dst++ = sum % 26 + 'a';
		src++;
	}
	return (uint64)len;
}

bool is_file_exist(char *path)
{
	if(!path)
		return false;
	if(!access(path,F_OK))
		return true;
	return false;
}

void ratio_print(char* ratio_message, int cur, int finish, bool end)
{
	static float print_ratio = 0;
	float ratio = 0;

	if(user_arg.verbose)
		return;
	if(cur > finish)
		cur = finish;

	ratio = cur / (float)finish;
	if(!end && ratio > 1)
		ratio = 0.99;

	print_ratio += 0.01;
	if(print_ratio >= ratio)
		print_ratio = ratio;

	if(!end)
		printf("\r\033[K%s==================%d%% ", ratio_message, (int)(print_ratio * 100));
	else {
		print_ratio = 1;
		printf("\r\033[K%s==================%d%% ", ratio_message, (int)(print_ratio * 100));
		printf("\r\033[K");
	}
	fflush(stdout);
}

char* random_str(void)
{
	int pro_num = rand() % 0x0fffffff;
	char *result = NULL;

	memset(num_buff, 0, NUMBER_BUFF_LEN);
	memset(random_str_buff, 0, RANDOM_STR_BUFF_LEN);
	sprintf(num_buff, "%d", pro_num);
	str_exchange(num_buff, strlen(num_buff), random_str_buff);

	result = strdup(random_str_buff);
	return result;
}